namespace FIREFLYX {
    /** 后处理效果  运动模糊 */
    export class PostEffectMotionBlur implements IExample {
        public Init(canvas: HTMLCanvasElement): void {
            console.log("PostEffectMotionBlur");
            let gl = canvas.getContext("webgl2");

            //app init
            App.init(gl.canvas as any);
            //简单观察相机
            let cVEnv = GenCamViewEnv();
            let cam = cVEnv.camera;
            let camHover = cVEnv.camHover;
            camHover.tiltAngle = 70;
            camHover.distance = 10;
            //添加 后处理效果 组件
            let depthOfField = cam.entity.addComponent<MotionBlur>(MotionBlur);
            depthOfField.setMotionBlur(0.5);
            //灯光
            const light = GenMainLight(45);

            //模型节点
            let modles: GameObject[] = [];
            //中心圆柱体
            let cylinder = GameObjectUtil.createPrimitive(GameObjectPrimitiveType.CYLINDER);
            cylinder.transform.scale = new Vector3(2, 2, 2);
            modles.push(cylinder);
            //matrix 整列
            let size = 5;
            let halfS = size / 2;
            let gap = 8;
            for (let y = 0; y < size; y++) {
                for (let x = 0; x < size; x++) {
                    // let cube = new GameObject(`unit_${x}_${y}`);
                    let cube = GameObjectUtil.createPrimitive(GameObjectPrimitiveType.CYLINDER);
                    cube.transform.position = new Vector3((x - halfS) * gap, 0, (y - halfS) * gap);
                    cube.transform.scale = new Vector3(2, 2, 2);
                    modles.push(cube);
                }
            }

        }
    }

    /** 实现 MotionBlur 效果的脚本组件 */
    class MotionBlur extends Script {
        private _mtr: Material;
        private _mtrMix: Material;
        private _blurAmount = 0.95;
        private _cacheRT: RenderTexture2D;

        private makeShaderMix() {
            //后处理 叠加 顶点程序
            let postEffBaseVS = `#version 300 es
                layout (location = 0) in vec4 a_Position; //顶点 位置 是有默认值的 (0,0,0,1)
                layout (location = 3) in vec2 a_UV;       //UV 纹理坐标
                out vec2 v_uv;
                void main() {
                    v_uv = a_UV;
                    vec4 pos = vec4(a_Position.xyz , 1.0);
                    gl_Position = pos;
                }
            `;

            //后处理 叠加 片源程序
            let postEffBaseFS = `#version 300 es
                precision mediump float;
                uniform sampler2D u_mainTex;
                uniform sampler2D u_mixTex;
                uniform float u_blurAmount;
                in vec2 v_uv;
                out vec4 color;
                void main(){
                    vec4 texColor = texture(u_mainTex , v_uv);    //纹理
                    vec4 texColor1 = texture(u_mixTex , v_uv);    //纹理
                    // vec4 fColor = (texColor *  (1.0 - u_blurAmount)) + (texColor1 * u_blurAmount);
                    vec4 fColor = mix(texColor , texColor1 , u_blurAmount);
                    color = fColor;
                }
            `;

            //glsl
            const vs = new GLSL();
            vs.setCode(postEffBaseVS);
            const fs = new GLSL();
            fs.setCode(postEffBaseFS);

            //shader
            let result: Shader = new Shader();
            result.lightMode = RenderPipeline.LM_FORWARD;
            result.vertexGLSL = vs;
            result.fragmentGLSL = fs;
            //unifrom 默认值
            result.definePropertyMap = {};

            result.definePropertyMap.u_mainTex = {
                type: "texture",
                value: "White",
            };
            result.definePropertyMap.u_mixTex = {
                type: "texture",
                value: "White",
            };

            //apply
            result.apply();

            return result;
        }

        public setMotionBlur(blurAmount = 0.95) {
            this._blurAmount = blurAmount;
            this.setMaterial();
        }

        private setMaterial() {
            if (!this._mtrMix) return;
            this._mtrMix.setProperty("u_blurAmount", this._blurAmount);
        }

        public start() {
            let sh = DefaultAsset.GetShader(BUILTIN_SHADER_POSTEFF_IMAGE);
            this._mtr = new Material("copyImage");
            this._mtr.shader = sh;

            let sh1 = this.makeShaderMix();
            this._mtrMix = new Material("MotionBlur mix");
            this._mtrMix.shader = sh1;

            this._cacheRT = new RenderTexture2D("cacheRT", true, false, false);

            this.setMaterial();
        }

        public onRenderImage(src: RenderTexture2D, dest: RenderTexture2D) {
            //渲染
            this._cacheRT.setSize(src.width, src.height);
            this._mtrMix.setProperty("u_mixTex", this._cacheRT);

            Graphics.Blit(src, dest, this._mtrMix);  //直接从src 绘制到 dest
            Graphics.Blit(dest, this._cacheRT, this._mtr);  //直接从src 绘制到 dest

        }
    }
}